package stone926.mods.more_enchantments.enchantments;

import net.minecraft.block.BlockState;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentTarget;
import net.minecraft.entity.*;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.boss.dragon.EnderDragonEntity;
import net.minecraft.entity.boss.dragon.EnderDragonPart;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.HoeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.particle.DustParticleEffect;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3f;
import net.minecraft.world.World;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;
import stone926.mods.more_enchantments.damage.StoneDamageSource;
import stone926.mods.more_enchantments.enchantments.cleanUp.AbstractCleanUpEnchantment;
import stone926.mods.more_enchantments.interfaces.IEntityScheduleDie;
import stone926.mods.more_enchantments.util.EnchantmentUtil;

import java.util.List;
import java.util.Random;

public class SacrificeEnchantment extends Enchantment {

  public SacrificeEnchantment() {
    super(Rarity.VERY_RARE, EnchantmentTarget.DIGGER, new EquipmentSlot[]{EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND});
  }

  public static int getRadius(int lvl) {
    return lvl * 7;
  }

  public static boolean killNearByEntities(World world, PlayerEntity player, int lvl) {
    Box range = Box.from(player.getPos()).expand(getRadius(lvl), lvl / 1.5, getRadius(lvl));
    List<Entity> entityList = world
      .getEntitiesByClass(Entity.class, range, EntityPredicates.VALID_ENTITY)
      .stream()
      .filter(e -> !(e instanceof PlayerEntity))
      .filter(e -> !(e instanceof EnderDragonPart))
      .filter(e -> !(e instanceof EnderDragonEntity))
      .filter(e -> !(e instanceof WitherEntity))
      .filter(e -> !(e instanceof LightningEntity))
      .toList();
    boolean isSuccess = false;
    for (Entity e : entityList) {
      Random r = e.world.getRandom();
      ((IEntityScheduleDie) e).scheduleToDie(100);
      ((IEntityScheduleDie) e).setParticle(
        new DustParticleEffect(new Vec3f((float) (0 + r.nextGaussian() / 2), 1, 1), 3),
        lvl,
        0.1, 1.4, 0.1,
        0.2 + lvl * 0.1
      );
      ((IEntityScheduleDie) e).setNeedDie(true);
      ((IEntityScheduleDie) e).setAttacker(player);
      ((IEntityScheduleDie) e).setLvl(lvl);
      if (!isSuccess) isSuccess = true;

    }
    return isSuccess;
  }

  public static void sacrificeAfterEntityDeath(PlayerEntity playerEntity, int lvl) {
    if (lvl > 0) {
      if (!playerEntity.getAbilities().creativeMode) {
        PlayerInventory inventory = playerEntity.getInventory();
        int r = playerEntity.getRandom().nextInt(inventory.size());
        ItemStack stack = inventory.getStack(r);
        if (!EnchantmentUtil.hasEnchantment(MoreEnchantmentsMod.SACRIFICE_RESISTANCE, stack))
          playerEntity.getInventory().removeStack(r);
        playerEntity.damage(StoneDamageSource.FATAL_SACRIFICE_ENCHANTMENT, Integer.MAX_VALUE);
        playerEntity.addExperienceLevels(-lvl);
      }
    }
  }

  public static void sacrificeDuringTiming(PlayerEntity playerEntity, int lvl) {
    playerEntity.damage(StoneDamageSource.SACRIFICE_ENCHANTMENT, playerEntity.getHealth() / 10F);
  }

  public static void boostDyingLivingEntity(LivingEntity l, int lvl) {
    l.addStatusEffect(new StatusEffectInstance(StatusEffects.SPEED, 2, lvl - 1));
    l.addStatusEffect(new StatusEffectInstance(StatusEffects.JUMP_BOOST, 2, lvl - 1));
    l.addStatusEffect(new StatusEffectInstance(StatusEffects.GLOWING, 2));
  }

  public static void startRite(World world, PlayerEntity player, int lvl) {
    if (!(world instanceof ServerWorld server)) return;
    int lightningCount = lvl * 2 + player.getRandom().nextInt(lvl * 3);
    for (int i = 0; i < lightningCount; i++) {
      int x1 = player.getRandom().nextInt(2) == 0 ? 1 : -1;
      int x2 = player.getRandom().nextInt(2) == 0 ? 1 : -1;
      double lightningX = player.getX() + x1 * (8 + player.getRandom().nextInt(20));
      double lightningZ = player.getZ() + x2 * (8 + player.getRandom().nextInt(20));
//      double lightningY = world.getTopY(Heightmap.Type.WORLD_SURFACE_WG, (int) lightningX, (int) lightningZ);
      LightningEntity lightning = new LightningEntity(EntityType.LIGHTNING_BOLT, world);
//      lightning.setPosition(lightningX, lightningY, lightningZ);
      lightning.setPosition(lightningX, player.getY(), lightningZ);
      world.spawnEntity(lightning);
    }

    if (!player.getAbilities().creativeMode) {
      server.setTimeOfDay(18000);
      player.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, lvl * 10));
    }
  }

  public static void onEntityDie(World world, Entity entity, int lvl) {
    if (world instanceof ServerWorld server
      && entity != null
      && !entity.isAlive()
      && world.random.nextDouble() <= lvl * 0.14
    ) {
      BlockPos pos = entity.getBlockPos();
      BlockState state = MoreEnchantmentsMod.CHRYSANTHEMUM.getDefaultState();
      if (world.random.nextInt(5) == 0 || entity instanceof HostileEntity)
        state = MoreEnchantmentsMod.BLACK_MANDALA.getDefaultState();
      if (world.getBlockState(pos).isAir() && state.canPlaceAt(world, pos)) {
        world.setBlockState(pos, state, 3);
      }
    }
  }

  @Override
  public int getMaxLevel() {
    return 5;
  }

  @Override
  public boolean isAcceptableItem(ItemStack stack) {
    return stack.getItem() instanceof HoeItem;
  }

  @Override
  protected boolean canAccept(Enchantment other) {
    return !(other instanceof AbstractCleanUpEnchantment)
      && !(other == MoreEnchantmentsMod.DESTROY_CURSE);
  }

  @Override
  public void onTargetDamaged(LivingEntity user, Entity target, int level) {
    super.onTargetDamaged(user, target, level);
    if (!user.getEntityWorld().isClient) {
      ((ServerWorld) user.getEntityWorld()).spawnParticles(
        new DustParticleEffect(new Vec3f(0.9F, 0.3F, 1), 3),
        target.getX(),
        target.getY() + target.getHeight(),
        target.getZ(),
        60,
        0.2, 0.2, 0.2,
        0
      );
    }
  }

  @Override
  public float getAttackDamage(int level, EntityGroup group) {
    return -level * 2;
  }

}


